package com.example.caorl.jdbc.util;


import com.example.caorl.jdbc.handler.IResultSetHandler;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class JDBCTemplate {

    //DDL/DML模板

    /**
     * @param sql  预处理的sql语句
     * @param args 各个占位符相对应的对象
     */
    public static void update(String sql, Object... args) {
        Connection conn = null;
        //是PreparedStatement,不要写错
        PreparedStatement ps = null;
        try {
            //获取数据连接池里的连接对象
            conn = HikariUtil.getConn();
            //创建一个PreparedStatement将参数化的SQL语句发送给数据库
            ps = conn.prepareStatement(sql);
            //执行语句之前先要将数据传进去
            //！！！注意：这里设置占位符的索引从1开始，而不是0
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            ps.executeUpdate();//无参数
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            HikariUtil.close(conn, ps, null);
        }
    }

    public static <T> T queryArt(String sql, IResultSetHandler<T> rsd, Object... args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = HikariUtil.getConn();
            ps = conn.prepareStatement(sql);
            //将参数传进占位符中
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            //将读取到的结果集逐一读取，存到JavaBean中，以便读取出来
            return rsd.handle(rs);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            HikariUtil.close(conn, ps, rs);
        }
        return null;
    }

    //通用版

    /**
     * @param sql  预编译的sql语句，可以是查询一列，多列，或者聚合函数，分别对应一个类，多个类（集合），数据类型
     * @param rsd  处理结果集的方法，根据不同的查询结果，分别用接口的不同实现类来实现处理结果集的方法
     * @param args 方法的可变参数（和泛型结合在一起回导致堆污染），里面的参数是各个占位符相对应的值
     * @return 返回的类型由传进来的时候决定
     */
    public static <T> T queryBean(String sql, IResultSetHandler<T> rsd, Object... args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = HikariUtil.getConn();
            ps = conn.prepareStatement(sql);
            //将参数传进占位符中
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            return rsd.handle(rs);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            HikariUtil.close(conn, ps, rs);
        }
        return null;
    }
}
